<?php

namespace hiduoke\services\douyinMinApp;

use app\common\model\open\Open;
use app\common\model\open\OpenTemplate;
use app\common\model\platform\PlatformApp;
use app\common\model\platform\PlatformAppOpen;
use hiduoke\services\douyinMinApp\API\DouyinOpenApi;

use think\facade\Cache;

/**
 * Notes: 抖音服务商方法类
 * Create by :  刘泓宾<514660094@qq.com>
 * Copyright :  copyright (c) 多客怪兽, www.dkyx.cc
 * Created on:  2024/3/14 15:57
 */
class DouyinMinAppServer
{
    /**
     * 抖音服务商接口
     * @var DouyinOpenApi
     */
    protected $DouyinOpenAPI;
    /**
     * 小程序ID
     * @var int
     */
    public $platform_app_id;
    /**
     * 抖音小程序
     * @var PlatformApp|array|mixed|\think\Model|null
     */
    protected $platform_app;
    /**
     * @deprecated 服务商平台
     *
     * @var PlatformAppOpen|array|mixed|\think\Model|null
     */
    protected $platform_app_open;

    /**
     * 开放平台模型
     * @var Open|array|\think\Model|null
     */
    public $open;

    public $config;
    /**
     * 授权小程序 appid
     * @var mixed
     */
    public $authorization_appid;
    /**
     * 应用标识
     * @var mixed
     */
    public $addon_name;
    /**
     * 第三方小程序应用接口调用凭据
     * @var mixed
     */
    public $component_access_token;
    public $plaid;

    public $err_msg;
    public $err_code;

    /**
     * 模板模型
     * @var OpenTemplate|array|\think\Model|null
     */
    public $template;


    public function __construct($platform_app_id)
    {
        $this->platform_app_id = $platform_app_id;
        $this->platform_app = (new PlatformApp())->where(['id' => $platform_app_id])->find();
        $this->plaid = $this->platform_app['plaid'];
        $this->authorization_appid = $this->platform_app['appid'];
        $this->addon_name = $this->platform_app['addon_name'];
        $this->open = (new Open())->where(['addon_name' => $this->addon_name])->find();
        $this->template = (new OpenTemplate())->where(['addon_name' => $this->addon_name])->order('id','desc')->find();
        $this->config = $this->open['config'];
        $this->DouyinOpenAPI = new DouyinOpenApi($this->open['config']);
        $this->component_access_token = $this->open['other_data']['component_access_token'];
        $this->component_access_token_v2 = $this->open['other_data']['component_access_token_v2'] ?? '';
    }

    /**
     * 获取/找回授权码
     * @doc https://partner.open-douyin.com/docs/resource/zh-CN/thirdparty/API/smallprogram/authorization/findauthorizationcode
     * @return string
     */
    public function get_authorization_code()
    {
        $key = "gs.douyin.app.authorization_code." . $this->authorization_appid;
        if (Cache::get($key)) {
            return Cache::get($key);
        }
        $res = $this->DouyinOpenAPI->retrieveAuthorizationCode($this->component_access_token, $this->authorization_appid);
        if (isset($res['authorization_code'])) {
            Cache::set($key, $res['authorization_code'], $res['expires_in'] - 500);
            return $res['authorization_code'];
        } else {
            $this->err_msg = $res['message'];
            $this->err_code = $res['errno'];
            return false;
        }
    }

    /**
     * 获取授权小程序接口调用凭据[服务商]
     * @return mixed
     */
    public function get_authorizer_access_token()
    {
        $key = "gs.douyin.app.authorizer_access_token_v1." . $this->authorization_appid;
        $key_refresh = "gs.douyin.app.authorizer_refresh_token_v1." . $this->authorization_appid;
        if (Cache::get($key)) {
            return Cache::get($key);
        }
        if (Cache::get($key_refresh)) {
            // 刷新存在
            $res = $this->DouyinOpenAPI->refreshAuthorizerAccessToken($this->component_access_token, Cache::get($key_refresh));
        } else {
            $res = $this->DouyinOpenAPI->getAuthorizerAccessToken($this->component_access_token, $this->get_authorization_code());
        }
        if (isset($res['errno'])) {
            $this->err_msg = $res['message'];
            $this->err_code = $res['errno'];
            return false;
        } else {
            $authorizer_access_token = $res['authorizer_access_token'];
            $authorizer_refresh_token = $res['authorizer_refresh_token'];
            Cache::set($key, $authorizer_access_token, $res['expires_in'] - 500);
            Cache::set($key_refresh, $authorizer_refresh_token, $res['refresh_expires_in'] - 500);
            return $authorizer_access_token;
        }
    }


    /**
     * 获取/找回授权码
     * @doc https://partner.open-douyin.com/docs/resource/zh-CN/thirdparty/API/smallprogram/authorization/findauthorizationcode
     * @return string
     */
    public function get_authorization_code_V2()
    {
        $key = "gs.douyin.app.authorization_code_V2." . $this->authorization_appid;
        if (Cache::get($key)) {
            return Cache::get($key);
        }
        $res = $this->DouyinOpenAPI->retrieveAuthorizationCode_V2($this->component_access_token_v2, $this->authorization_appid);
        if ($res['err_no'] == 0) {
            $data = $res['data'];
            Cache::set($key, $data['authorization_code'], $data['expires_in'] - 500);
            return $data['authorization_code'];
        } else {
            $this->err_msg = $res['err_msg'];
            $this->err_code = $res['err_no'];
            return false;
        }
    }

    /**
     * 获取授权小程序接口调用凭据
     * @return mixed
     */
    public function get_authorizer_access_token_V2()
    {
        $key = "gs.douyin.app.authorizer_access_token_v2." . $this->authorization_appid;
        $key_refresh = "gs.douyin.app.authorizer_refresh_token_v2." . $this->authorization_appid;
        if (Cache::get($key)) {
            return Cache::get($key);
        }
        if (Cache::get($key_refresh)) {
            // 刷新存在
            $res = $this->DouyinOpenAPI->refreshAuthorizerAccessToken_V2($this->component_access_token_v2, Cache::get($key_refresh));
        } else {
            $res = $this->DouyinOpenAPI->getAuthorizerAccessToken_V2($this->component_access_token_v2, $this->get_authorization_code_V2());
        }
        if ($res['err_no'] == 0) {
            $data = $res['data'];
            $authorizer_access_token = $data['authorizer_access_token'];
            $authorizer_refresh_token = $data['authorizer_refresh_token'];
            Cache::set($key, $authorizer_access_token, $data['expires_in'] - 500);
            Cache::set($key_refresh, $authorizer_refresh_token, $data['refresh_expires_in'] - 500);
            return $authorizer_access_token;
        } else {
            $this->err_msg = $res['err_msg'];
            $this->err_code = $res['err_no'];
            return false;
        }
    }

    /**
     * 获取授权链接
     * @return false|mixed
     */
    public function getLink()
    {
        $res = $this->DouyinOpenAPI->getGenLink($this->component_access_token, $this->platform_app_id);
        if (isset($res['errno'])) {
            $this->err_msg = $res['message'];
            $this->err_code = $res['errno'];
            return false;
        } else {
            return $res['link'];
        }
    }

    // 获取二维码
    public function getQrcode($version, $path = '')
    {
        $res = $this->DouyinOpenAPI->getQrcode($this->get_authorizer_access_token(), $version, $path);
        return $res;
    }


    /**
     * 登录
     * Create by :  刘泓宾<514660094@qq.com>
     * @param $code
     * @param $anonymous_code
     * @return mixed
     */
    public function login($code, $anonymous_code = '')
    {
        return $this->DouyinOpenAPI->login($this->get_authorizer_access_token(), $code, $anonymous_code);
    }


    public function info()
    {
        return $this->DouyinOpenAPI->info($this->get_authorizer_access_token());
    }

    /******************其他助手函数**************************/


    public function getOpenApi()
    {
        return $this->DouyinOpenAPI;
    }

    /**
     * @return PlatformApp|array|mixed|\think\Model|null
     */
    public function getPlatformApp(): mixed
    {
        return $this->platform_app;
    }

    /**
     * @return PlatformAppOpen|array|mixed|\think\Model|null
     * @deprecated 废除
     */
    public function getPlatformAppOpen(): mixed
    {
        return $this->platform_app_open;
    }


    public function getOpen()
    {
        return $this->open;
    }

    public function getTemplate()
    {
        return $this->template;
    }
}
